/**
 * Created with IntelliJ IDEA.
 * User: zzl
 * Date: 13-1-27
 * To change this template use File | Settings | File Templates.
 */
(function ($, undefined) {

    var BoxSelector = function (tbody) {
        var me = this;
        me.$tbody = $(tbody);
        me.selectedRows = [];
        me.setup();
    };

    var proto = { constructor: BoxSelector };
    BoxSelector.prototype = proto;

    proto.setup = function () {
        var me = this;
        me.$tbody.on('mousedown.boxSelector', function (e) {
            me.tbody_mousedown(e);
        });
        $(document).on('mouseup.boxSelector', function (e) {
            me.document_mouseup(e);
        });
        me.$selectBox = $('<div class="selectBox" style="display:none;"></div>');
        me.$selectBox.appendTo(document.body);
    };

    proto.tbody_mousedown = function (e) {
        var me = this;
        if (!$(e.target).is('[tabindex]')) {
            me.downPt = {x: e.pageX, y: e.pageY};
            $(document).on('mousemove.boxSelector', function (e) {
                me.document_mousemove(e);
            });
            me.$downRow = $(e.target).parents('tr:first');
        }
    };

    proto.document_mousemove = function (e) {
        var me = this;
        var downPt = me.downPt;
        if (!downPt) {
            return;
        }
        var x1 = downPt.x;
        var y1 = downPt.y;
        var x2 = e.pageX;
        var y2 = e.pageY;
        var t;
        if (x1 > x2) {
            t = x1;
            x1 = x2;
            x2 = t;
        }
        if (y1 > y2) {
            t = y1;
            y1 = y2;
            y2 = t;
        }
        if (y1 < me.minY) {
            y1 = me.minY;
        }
        if (y2 > me.maxY) {
            y2 = me.maxY;
        }
        if (me.selecting) {
            me.$selectBox.css({
                left: (x1 - 1) + 'px',
                top: (y1 - 1) + 'px',
                width: (x2 - x1) + 'px',
                height: (y2 - y1) + 'px',
                display: 'block'
            });
            me.moveRow = me.findRowAt(e.pageY);
            if (me.moveRow && me.moveRow !== me.lastMoveRow) {
                me.lastMoveRow = me.moveRow;
                me.updateSelection();
            }
        }
        else if (x2 - x1 > 3 || y2 - y1 > 3) {
            me.beginSelect();
        }
        var scrollTop = $(window).scrollTop();
        var height = $(window).height();
        var newScrollTop;
        if (e.pageY > scrollTop + height) {
            newScrollTop = e.pageY - height;
        }
        else if (e.pageY < scrollTop) {
            newScrollTop = e.pageY;
        }
        if (newScrollTop) {
            setTimeout(function () {
                $(window).scrollTop(newScrollTop);
            }, 1);
        }
    };

    proto.beginSelect = function () {
        var me = this;
        me.selecting = true;
        me.$allRows = me.$tbody.children();
        me.$allRows.removeClass('selected');
        me.downRowIndex = jsex.indexOf(me.$allRows, me.$downRow[0]);

        me.$rows = me.$tbody.children(':visible');
        var rowTops = [];
        for(var n = 0; n < me.$rows.length; n++) {
            rowTops.push($(me.$rows[n]).offset().top);
        }
        me.rowTops = rowTops;

        me.minY = me.$tbody.offset().top;
        me.maxY = me.$tbody.offset().top + me.$tbody.height();

        $(window).on('blur.boxSelector', function () {
            me.endSelect();
            $(window).off('blur.boxSelector');
        });

    };

    proto.findRowAt = function(y) {
        var me = this;
        var tops = me.rowTops;
        for(var n = tops.length - 1; n >= 0; --n) {
            if(y >= tops[n]) {
                return me.$rows[n];
            }
        }
        return me.$rows[0];
    };

    proto.updateSelection = function () {
        var me = this;
        var index1 = me.downRowIndex;
        var index2 = jsex.indexOf(me.$allRows, me.moveRow);
        if (index1 > index2) {
            var t = index1;
            index1 = index2;
            index2 = t;
        }
        $(me.selectedRows).removeClass('selected');
        var rows = [];
        for (var n = index1; n <= index2; n++) {
            var row = me.$allRows[n];
            if(!$(row).hasClass('hidden')) {
                rows.push(row);
            }
        }
        $(rows).addClass('selected');
        me.selectedRows = rows;
    };

    proto.document_mouseup = function (e) {
        var me = this;
        me.endSelect();
    };

    proto.endSelect = function () {
        var me = this;
        if (me.downPt) {
            $(document).off('mousemove.boxSelector');
        }
        if (me.selecting && me.selectedRows.length) {
            me.$tbody.trigger('boxSelected', [me.selectedRows]);
            me.$selectBox.hide();
            me.selecting = false;
            me.$allRows = null;
        }
        me.reset();
    };

    proto.reset = function () {
        var me = this;
        me.downPt = null;
        me.selecting = false;
        me.$downRow = null;
        me.moveRow = null;
        me.lastMoveRow = null;
        me.$rows = undefined;
        me.rowTops = [];
        me.selectedRows = [];
    };

    $.fn.boxSelector = $.addPluginFn('boxSelector', BoxSelector);


})(jQuery);